package com.huawei.cloudphone.virtualdevice.location;

import static com.huawei.cloudphone.api.CloudPhoneParas.DEV_TYPE_LOCATION;
import static com.huawei.cloudphone.jniwrapper.JNIWrapper.LOCATION_DATA;
import static com.huawei.cloudphone.virtualdevice.common.VirtualDeviceProtocol.MSG_HEADER_LEN;

import android.content.Context;
import android.os.Build;
import android.util.Log;

import androidx.annotation.RequiresApi;

import com.huawei.cloudphone.api.CloudPhonePermissionRequestListener;
import com.huawei.cloudphone.common.CASLog;
import com.huawei.cloudphone.virtualdevice.common.IVirtualDeviceDataListener;
import com.huawei.cloudphone.virtualdevice.common.VirtualDeviceManager;
import com.huawei.cloudphone.virtualdevice.common.VirtualDeviceProtocol;
import java.nio.ByteBuffer;

public class VirtualLocationManager extends VirtualDeviceManager {
    private static final String TAG = "VirtualLocationManager";
    public static final short OPT_LOCATION_OPEN_REQ = 0x0;
    public static final short OPT_LOCATION_CLOSE_REQ = 0x1;
    public static final short OPT_LOCATION_DATA = 0x2;
    public static final short OPT_GNSS_MEASUREMENT_OPEN_REQ = 0x3;
    public static final short OPT_GNSS_MEASUREMENT_CLOSE_REQ = 0x4;
    public static final short OPT_GNSS_MEASUREMENT_DATA = 0x5;

    private VirtualLocation mVirtualLocation;
    private VirtualDeviceProtocol mVirtualDeviceProtocol;
    private CloudPhonePermissionRequestListener mPermissionListener;

    private boolean mIsLocationOpen = false;
    private boolean mIsGnssMeasurementOpen = false;
    private static final int TYPE_LOCATION = 0;
    private static final int TYPE_GNSS_MEASUREMENT = 1;

    public VirtualLocationManager(VirtualDeviceProtocol virtualDeviceProtocol, Context context) {
        mVirtualDeviceProtocol = virtualDeviceProtocol;
        mVirtualLocation = new VirtualLocation(context);
        mVirtualLocation.registerLocationDataListener(new LocationDataListener());
        mVirtualLocation.registerGnssMeasurementsDataListener(new GnssMeasurementsDataListener());
    }

    @Override
    public void setPermissionListener(CloudPhonePermissionRequestListener listener) {
        mPermissionListener = listener;
    }

    @RequiresApi(api = Build.VERSION_CODES.P)
    public void init() {
        if (mIsLocationOpen) {
            mVirtualLocation.requestUpdates(mPermissionListener, TYPE_LOCATION);
        }
        if (mIsGnssMeasurementOpen) {
            mVirtualLocation.requestUpdates(mPermissionListener, TYPE_GNSS_MEASUREMENT);
        }
    }

    @RequiresApi(api = Build.VERSION_CODES.N)
    public void stop() {
        mVirtualLocation.closeLocationUpdates();
        mVirtualLocation.closeGnssMeasurementUpdates();
    }

    @RequiresApi(api = Build.VERSION_CODES.P)
    public void processMsg(VirtualDeviceProtocol.MsgHeader header, byte[] body) {
        Log.i(TAG,"processMsg:" + header);
        switch (header.mOptType) {
            case OPT_LOCATION_OPEN_REQ:
                Log.i(TAG, "processMsg: open location");
                mIsLocationOpen = true;
                mVirtualLocation.requestUpdates(mPermissionListener, TYPE_LOCATION);
                break;
            case OPT_LOCATION_CLOSE_REQ:
                Log.i(TAG, "processMsg: close location");
                mIsLocationOpen = false;
                mVirtualLocation.closeLocationUpdates();
                break;
            case OPT_GNSS_MEASUREMENT_OPEN_REQ:
                Log.i(TAG, "processMsg: open gnss measurement");
                mIsGnssMeasurementOpen = true;
                mVirtualLocation.requestUpdates(mPermissionListener, TYPE_GNSS_MEASUREMENT);
                break;
            case OPT_GNSS_MEASUREMENT_CLOSE_REQ:
                Log.i(TAG, "processMsg: close gnss measurement");
                mIsGnssMeasurementOpen = false;
                mVirtualLocation.closeGnssMeasurementUpdates();
                break;
            default:
                Log.e(TAG, "processMsg: error opt type");
        }
    }

    class LocationDataListener implements IVirtualDeviceDataListener {
        @Override
        public void onRecvData(Object... args) {
            String body = (String) args[0];
            int type = 0;
            int bodyLen = body.getBytes().length;
            int rspMsgLen = bodyLen + MSG_HEADER_LEN;
            VirtualDeviceProtocol.MsgHeader header = new VirtualDeviceProtocol.MsgHeader(OPT_LOCATION_DATA, DEV_TYPE_LOCATION, (short) type, rspMsgLen);
            byte[] rspBody = new byte[bodyLen];
            System.arraycopy(body.getBytes(), 0, rspBody, 0, bodyLen);
            mVirtualDeviceProtocol.sendMsg(header, rspBody, LOCATION_DATA);
        }
    }

    class GnssMeasurementsDataListener implements IVirtualDeviceDataListener {

        @Override
        public void onRecvData(Object... args) {
            int type = 0;
            ByteBuffer body = (ByteBuffer) args[0];
            int bodyLen = body.position();
            int rspMsgLen = bodyLen + MSG_HEADER_LEN;
            VirtualDeviceProtocol.MsgHeader header = new VirtualDeviceProtocol.MsgHeader(OPT_GNSS_MEASUREMENT_DATA, DEV_TYPE_LOCATION, (short) type, rspMsgLen);
            byte[] rspBody = new byte[bodyLen];
            System.arraycopy(body.array(), 0, rspBody, 0, bodyLen);
            mVirtualDeviceProtocol.sendMsg(header, rspBody, LOCATION_DATA);
        }
    }
}
